{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2D Decision Integrator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a model of perceptual decision making using a two dimensional integrator. As mentioned in the book, the goal is to construct a simple model of perceptual decision making without being concerned with establishing how good or bad it is. \n",
    "\n",
    "Rather than having two different integrators for each dimension, you will build the model using a single two dimensional integrator. This integrator can be used irrespective of the task demands since it effectively integrates in every direction simultaneously. This is neurally more efficient due to the reasons explained in the book."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Setup the environment\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "\n",
    "import nengo\n",
    "from nengo.processes import WhiteNoise\n",
    "from nengo.utils.functions import piecewise\n",
    "from nengo.utils.matplotlib import rasterplot\n",
    "from nengo.dists import Uniform"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The model has four ensembles: MT representing the motion area, LIP representing the lateral intraparietal area, input and output of the 2D integrator. The parameters used in the model are as described in the book. The 2D integrator resides in LIP. As discussed in the book an integrator requires two connections: here, the input from MT to LIP and the feedback connection from LIP to LIP.\n",
    "\n",
    "Here, you will provide a an input of (-0.5, 0.5) to the model spanning over a period of 6 seconds to observe the model behaviour. In order to inject noise while the simulation runs, you can use the 'noise' parameter when creating ensembles as shown. The reason for injecting noise is explained in the book. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "model = nengo.Network(label='2D Decision Integrator', seed=11)\n",
    "with model:\n",
    "    # Input\n",
    "    input1 = nengo.Node(-0.5)\n",
    "    input2 = nengo.Node(0.5)\n",
    "    \n",
    "    # Ensembles \n",
    "    input = nengo.Ensemble(100, dimensions=2)\n",
    "    MT = nengo.Ensemble(100, dimensions=2, noise=WhiteNoise(dist=Uniform(-0.3,0.3)))\n",
    "    LIP = nengo.Ensemble(200, dimensions=2, noise=WhiteNoise(dist=Uniform(-0.3,0.3)))\n",
    "    output = nengo.Ensemble(100, dimensions=2, noise=WhiteNoise(dist=Uniform(-0.3,0.3)))\n",
    "     \n",
    "    weight = 0.1\n",
    "    # Connecting the input signal to the input ensemble\n",
    "    nengo.Connection(input1, input[0], synapse=0.01)   \n",
    "    nengo.Connection(input2, input[1], synapse=0.01) \n",
    "    \n",
    "    # Providing input to MT ensemble\n",
    "    nengo.Connection(input, MT, synapse=0.01) \n",
    "    \n",
    "    # Connecting MT ensemble to LIP ensemble\n",
    "    nengo.Connection(MT, LIP, transform=weight, synapse=0.1) \n",
    "    \n",
    "    # Connecting LIP ensemble to itself\n",
    "    nengo.Connection(LIP, LIP, synapse=0.1) \n",
    "    \n",
    "    # Connecting LIP population to output\n",
    "    nengo.Connection(LIP, output, synapse=0.01) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run the Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Import the nengo_gui visualizer to run and visualize the model.\n",
    "from nengo_gui.ipython import IPythonViz\n",
    "IPythonViz(model, \"ch8-2d-decision-integrator.py.cfg\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Press the play button in the visualizer to run the simulation. You should see the graphs as shown in the figure below.\n",
    "\n",
    "The `output` plot on the bottom-right shows the output of the 2D decision integrator which is represented by a single two dimensional output ensemble. You can see that as MT encodes the input over time, LIP slowly moves towards the same direction as it acuumulates evidence that there is sustained motion in that direction.\n",
    "\n",
    "Thus MT moves LIP in the right direction and once past a certain threshold, the output neurons start firing. To visualize this: \n",
    "<br>1) Select 'spikes' from the right-click menu of the output ensemble. This will display a spike plot.\n",
    "<br>2) Run the simulation and then slide the blue box in the simulation control bar backwards. \n",
    "<br>3) You will see that the spikes become stronger once past a certain threshold (i.e., when LIP starts following MT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.display import Image\n",
    "Image(filename='ch8-2d-decision-integrator.png')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
